<template>
  <div class="m-e" id="m-e-id">
    <div class="m-e-main">
      <div class="m-e-main_toolbar" :style="isThemeLightOrBlack ? 'background-color: #fff; box-shadow: 0px 2px 5px #ddd;' : 'background-color: #1e1e1e; box-shadow: 0px 2px 5px #111;'">
        <div class="m-e-main_toolbar_left">
          <span>日志 - {
   
   {
   
    title }}</span>
        </div>

        <div class="m-e-main_toolbar_right" :style="isThemeLightOrBlack ? 'color: #000' : 'color: #fff'">
          <a title="查找" @click="findByKeyword"><i class="fa fa-search"/></a>
          <a title="回到顶部" @click="scrollToTop"><i class="fa fa-chevron-circle-up"/></a>
          <a title="回到底部" @click="scrollToBottom"><i class="fa fa-chevron-circle-down"/></a>
          <a title="是否截断换行" @click="setEditorWordWrap"><i class="fa fa-bars"/></a>
          <a title="切换白天或暗夜模式" @click="setEditorTheme"><i class="fa fa-adjust"/></a>
          <a :title="fullScreen ? '退出全屏' : '全屏显示'" @click="handleFullScreenClick"><i :class="fullScreen ? 'fa fa-compress' : 'fa fa-arrows-alt'"/></a>
          <a title="下载日志" @click="handleDownloadLogClick"><i class="fa fa-download" style="position: relative; top: 2px"/></a>
        </div>
      </div>
      <div :id="id" class="m-e-main_container" :style="'height: ' + height"></div>
    </div>
  </div>
</template>

<script>
// 引用 font-awesome 资源
import 'font-awesome/css/font-awesome.min.css';

// 先汉化 monaco
import {
   
    setLocaleData } from "monaco-editor-nls"
import zh_CN from "monaco-editor-nls/locale/zh-hans"
setLocaleData(zh_CN)

// 再加载 monaco ，才能汉化成功
import * as me from 'monaco-editor'

export default {
   
   
  props:[
    'editorParams'
  ],
  data: () => ({
   
   
    editor: null,// 编辑器对象
    id: null,// 编辑器DOM节点ID
    title: '',// 编辑器标题
    content: '',// 编辑器内容
    height: 'auto',// 编辑器高度
    readOnly: true,// 编辑器是否禁用
    isScrollToBottom: false, // 是否滚动到底部

    // 其他配置项...
    fullScreen: false,// 是否全屏状态
    wordWrap: false,// 当单行文本太长时截断换行，true 为换行，false 为不换行
    isThemeLightOrBlack: false,// 明亮或暗夜模式，true 为白天模式，false 为暗夜模式

  }),
  mounted() {
   
   
    /**
     * 监听全屏显示状态
     */
    let that = this;
    window.onresize = function() {
   
   
      if (!document.fullscreenElement) {
   
   
        that.fullScreen = false;
      } else {
   
   
        that.fullScreen = true;
      } 
    }
  },
  watch: {
   
   
    /**
     * 深度监听富文本参数
     */
    "editorParams": {
   
   
        handler: function(newVal, oldVal) {
   
   
          // console.log('newVal =>', newVal, ' | oldVal =>', oldVal);
          if (oldVal == null && newVal != null) {
   
   
            // 首次变化
            this.id = newVal.id;
            this.title = newVal.title;
            this.content = newVal.content;
            this.height = 'calc(' + newVal.height + ' - 42px)';
            this.readOnly = newVal.readOnly;
            this.isScrollToBottom = newVal.isScrollToBottom;
            this.initEditor(this.id, this.content, this.readOnly);
            if (this.isScrollToBottom) {
   
   
              this.scrollToBottom(); // 滚动到底部
            }
          } else if (newVal != null && newVal != null) {
   
   
            // 二次变化
            this.title = newVal.title;
            this.content = newVal.content;
            this.isScrollToBottom = newVal.isScrollToBottom;
            if (this.isScrollToBottom) {
   
   
              this.editor.setValue(this.content);
              this.scrollToBottom(); // 滚动到底部
            } else {
   
   
              this.editor.setValue(this.content);
            }
            // this.setEditorContent(this.content);
          }
        },
        immediate: true,
        deep: true
    },
  },
  methods: {
   
   
    /**
     * 实例化在线代码编辑器
     * 
     * 文档地址：https://microsoft.github.io/monaco-editor/api/index.html
     */
    async initEditor(id, content, readOnly) {
   
   
      // 异步获取节点，确保 Dom 节点已经渲染完成，不可删
      let dom = await document.getElementById(this.id);
      const monaco = require("monaco-editor/esm/vs/editor/editor.api");
      this.editor = monaco.editor.create(document.getElementById(id), {
   
   
          value: content,// 编辑器内容
          language: 'python',// 选择支持语言
          automaticLayout: true,// 是否自动布局
          theme: 'vs-dark',// 官方自带三种主题：vs、hc-black、vs-dark
          readOnly: readOnly,// 设置是否只读
          wordWrap: this.wordWrap ? 'on' : 'off',// 设置启用截断功能
          scrollBeyondLastLine: false,// 滚动完最后一行后再滚动一屏幕

          // 滚动条
          // scrollbar: {
   
   
          //   verticalScrollbarSize: 15,
          //   horizontalScrollbarSize: 15
          // },

          // 是否开启小地图
          minimap: {
   
   
            enabled: true
          },
      });

      // 设置编辑器滚动到最底部
      // this.scrollToBottom();
    },

    /**
     * 设置编辑器的内容且滚动到最底部
     */
    setEditorContent(val) {
   
   
      this.editor.setValue(val);
      this.scrollToBottom();
    },

    /**
     * 获取编辑器的内容
     */
    getEditorContent() {
   
   
      this.editor.getValue();
    },

    /**
     * 打开编辑器查找功能
     */
    findByKeyword() {
   
   
      try {
   
   
        // 先聚焦编辑器
        this.editor.focus();

        // 从模型中获取要查找的字符串范围 new Range(startLineNumber, startColumn, endLineNumber, endColumn)
        this.editor.setSelection(new me.Range(1, 9999, 1, 10000));

        // 触发查找操作
        // this.editor.getAction('actions.find').run();// 查找方式一
        this.editor.trigger('', 'actions.find');// 查找方式二
      } catch(error) {
   
   
        console.log(error);
      }
    },

    /**
     * 设置编辑器从只读变成可写
     */
    setEditorRW() {
   
   
      this.editor.updateOptions({
   
   readOnly: false});
    },

    /**
     * 设置编辑器开关截断功能
     */
    setEditorWordWrap() {
   
   
      this.wordWrap = this.wordWrap ? false : true;
      if (this.wordWrap) {
   
   
        this.editor.updateOptions({
   
   wordWrap: 'on'});
      } else {
   
   
        this.editor.updateOptions({
   
   wordWrap: 'off'});
      }
    },

    /**
     * 设置编辑器明亮或暗夜模式
     */
    setEditorTheme() {
   
   
      this.isThemeLightOrBlack = this.isThemeLightOrBlack ? false : true;
      if (this.isThemeLightOrBlack) {
   
   
        this.editor.updateOptions({
   
   theme: 'vs'});
      } else {
   
   
        this.editor.updateOptions({
   
   theme: 'vs-dark'});
      }
    },

    /**
     * 设置编辑器滚动到最顶部
     */
    scrollToTop() {
   
   
      this.editor.setScrollPosition({
   
   scrollTop: 0});
    },

    /**
     * 设置编辑器滚动到最底部
     */
    scrollToBottom() {
   
   
      // this.editor.revealLineInCenter(99999);
      this.editor.revealLine(this.editor.getModel().getLineCount());
    },

    /**
     * 全屏显示句柄
     */
    handleFullScreenClick () {
   
   
            const element = document.getElementById('m-e-id');
      if (!document.fullscreenElement) {
   
   
        element.requestFullscreen();
      } else {
   
   
        document.exitFullscreen();
      } 
    },

    /**
     * 下载日志句柄
     */
    handleDownloadLogClick() {
   
   
      this.exportFile(this.title, this.content);
    },

    /**
     * 下载日志
     */
    exportFile(name, data) {
   
   
      let url = window.URL || window.webkitURL || window;
      let blob = new Blob([data]);
      let event = document.createEvent("MouseEvents");
      event.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      let link = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
      link.href = url.createObjectURL(blob);
      link.download = name;
      link.dispatchEvent(event);
    }
  },
  /**
   * 销毁在线代码编辑器
   */
  beforeDestroy() {
   
   
    if (this.monacoEditor) {
   
   
      this.monacoEditor.dispose()
    }
  },
}
</script>

<style scoped>
  .m-e {
    width: 100%;
    height: 100%;
  }

    .m-e-main {
      width: 100%;
      height: 100%;
    }

      .m-e-main_toolbar {
        width: 100%;
        height: 40px;
        box-shadow: 0px 2px 5px #000;
        display: flex;
        position: relative;
        z-index: 99;
      }

        .m-e-main_toolbar_left {
          flex: 1;
          overflow: hidden;
        }

        .m-e-main_toolbar_right {
          margin-right: 15px
        }
  </style>